package study.JavaBase;

import java.io.*;

/**
 * date:2025.10.15
 * title:异常处理
 * author:fzy
 */
public class Java_16 {
    public static void main(String[] args) {
//        JavaBase.ExceptionClass.ExceptionTest();
        //    JavaBase.ThrowExceptionClass.finallyTest();
//        JavaBase.ThrowExceptionClass.finallyTest2();
        PaymentClass myAccount = new PaymentClass(20000);
        try {
            int num = 200;
            myAccount.payToShop(100, shopList.Banana);
            myAccount.payToShop(100, shopList.Orange);
        } catch (PaymentException e) {
            e.printStackTrace();
        }
    }
}

//错误类型
//检查性异常：用户错误或问题引起的异常，强制处理，通常try-catch
//运行时异常：不要求强制处理，由程序错误引起，如数组越界，空指针
//错误
//所有的异常类都是Throwable的子类
class ExceptionClass {
    //捕获异常
    static void ExceptionTest() {
        //数组越界
        try {
            byte[] b = new byte[2];
            System.out.println(b[2]);
        } catch (ArrayIndexOutOfBoundsException e) {
            //Throwable的方法
            String error = e.toString();
            System.out.println(error);
        }
    }

    //多重捕获块
    static void ExceptionTest2() {
//        try {
//            File file = new File("D:/java/te1st.txt");
//            FileInputStream fis = new FileInputStream(file);
//            fis.read();
//        } catch (Java_27.io.FileNotFoundException e) {
//            e.printStackTrace();
//        } catch (Java_27.io.IOException e) {
//            throw new RuntimeException(e);
//        }
    }

    //多重捕获快合并
    //注意点，合并的错误类型不可以由继承关系
    //catch不可以调用某个类的特殊方法
    static void ExceptionTest3() {
        try {
            File file = new File("D:/java/te1st.txt");
            FileInputStream fis = new FileInputStream(file);
            fis.read();
        } catch (IndexOutOfBoundsException | IOException e) {
            e.printStackTrace();
        }
    }
}

//Throw和Throws
//Throw用来抛出异常
//Throw用来告诉编译器我将要抛什么异常
class ThrowExceptionClass {
    static double ExceptionTest(int a) throws IllegalArgumentException, IllegalStateException {
        if (a == 0) {
            throw new IllegalArgumentException();
        } else {
            return (double) (100 / a);
        }

    }

    //finally
    //无论发生异常都会执行，在finally可以做清理或者释放操作
    static void finallyTest() {
        String fileName = "D:/java/test.txt";
        byte[] b_write = {'9', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
        File f = new File(fileName);
        try {
            FileInputStream fis = new FileInputStream(f);
            FileOutputStream fos = new FileOutputStream(f);
            fos.write(b_write);
            byte[] b_read = new byte[b_write.length];
            fis.read(b_read, 0, b_read.length);
            for (byte b : b_read) {
                System.out.print((char) b);
            }
            fis.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println('/');
            System.out.println("程序运行完毕");
        }
    }

    //try-with-resources
    //自由管理资源，确保关闭，无泄漏，无论代码是否操纵成功，都会在try执行之后关闭
    static void finallyTest2() {
        String fileName = "D:/java/test.txt";
        File f = new File(fileName);
        try (FileInputStream fis = new FileInputStream(f)) {
            byte[] b_read = new byte[fis.available()];
            int res = fis.read(b_read, 0, b_read.length);
            if (res == -1) {
                for (byte b : b_read) {
                    System.out.print((char) b);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//声明自定义异常
//所有异常都必须是Throwable的子类
//如果想要写一个检查类异常，需要继承Exception类
//如果想要写一个运行时异常，需要继承runtimeException

class PaymentException extends RuntimeException {
    private final double missingAmount;

    public PaymentException(double missingAmount) {
        this.missingAmount = missingAmount;
    }


    public double getMissingAmount() {
        return missingAmount;
    }

    public void printStackTrace() {
        System.out.println("余额不足，缺失金额" + missingAmount);
    }
}

//枚举：暂时用不明白
enum shopList {
    Apple,
    Banana,
    Orange,
}

class PaymentClass {
    public double account;

    public PaymentClass(double account) {
        this.account = account;
    }


    public void payToShop(int payNum, shopList shop) throws PaymentException {
        if (shop == shopList.Apple) {
            if (payNum * 100 > account) {
                double num = payNum * 100 - payNum;
                throw new PaymentException(num);
            } else {
                account -= 100;
                System.out.println("购买成功!，余额为" + this.account);
            }
        } else if (shop == shopList.Banana) {
            if (payNum * 200 > account) {
                double num = payNum * 200 - payNum;
                throw new PaymentException(num);
            } else {
                account -= payNum * 200;
                System.out.println("购买成功!，余额为" + this.account);
            }
        } else if (shop == shopList.Orange) {
            if (payNum * 300 > account) {
                double num = payNum * 300 - payNum;
                throw new PaymentException(num);
            } else {
                account -= 300;
                System.out.println("购买成功!，余额为" + this.account);
            }
        }
    }
}
